package br.com.frbb.ugvbr.accessory;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import com.android.future.usb.UsbAccessory;
import com.android.future.usb.UsbManager;

public class USBAccessoryManager {
	private static final String TAG = "ADK";
	
	private static String packageName = null;
	
	private static UsbManager deviceManager;
	private static UsbAccessory accessory;
	private static FileOutputStream outputStream = null;
	private static ParcelFileDescriptor parcelFileDescriptor = null;
	
	private static boolean enabled = false;
	private static boolean permissionRequested = false;
	private static boolean open = false;
	
	public static void init(Context context) {
		
		UsbAccessory[] accessories = null;
		packageName = context.getPackageName();

		if(enabled == false) {
			
			IntentFilter filter = new IntentFilter(packageName);
			
			filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
			filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
			
			context.registerReceiver(receiver, filter);
			
			// Resgata DevideManager
	    	deviceManager = UsbManager.getInstance(context);	
	    	
	    	// Caso o DeviceManager seja nulo
			if(deviceManager == null) {
				throw new USBAccessoryException("Device Manager is null");
			}
			
			// Resgata todos os acessórios
			accessories = deviceManager.getAccessoryList();
			
			// Caso não encontre nenhum acessório
			if(accessories == null || accessories.length <= 0) {
				throw new USBAccessoryException("No accessories found.");
			}
			
			// Seleciona o primeiro acesório
			accessory = accessories[0];

			// Caso o acessório não
			if(accessory == null) {
				
				// Verifica se solicitou permissão para utilizar dispositivo
				if(permissionRequested == false) {

					// Solicita permissão para utilizar o dispositivo
					askPermission(context, deviceManager, accessory);
					return;
				}
				else {
					throw new USBAccessoryException("No accessories found.");
				}
			}
			
			// Caso possua permissão para acessoar o acessório
			if(deviceManager.hasPermission(accessory)) {	
				openAccessory();
				
			}
			else if(permissionRequested == false) {
				// Solicita permissão para utilizar o dispositivo
				askPermission(context, deviceManager, accessory);
				return;
			}
			else {
				throw new USBAccessoryException("No accessories found.");
			}
		}
	}
	
	private static void askPermission(Context context, UsbManager deviceManager, UsbAccessory accessory) {
		// Solicita permissão para utilizar o dispositivo
		PendingIntent permissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(packageName), 0);
		deviceManager.requestPermission (accessory, permissionIntent);
		
		permissionRequested = true;
	}
	
	public static void disable(Context context){
		// Desabilita acessorio
		closeAccessory();
		
		// Desregistra Receiver
		try {
			context.unregisterReceiver(receiver);
		} catch (Exception e) {
		}
	}
	
	public static boolean isConnected() {
		return open;
	}
	
    // Receiver para tratamento dos Broadcast
    private static final BroadcastReceiver receiver = new BroadcastReceiver() {
    	@Override
    	public void onReceive(Context context, Intent intent) {
    		
    		// Resgata ação
    		String action = intent.getAction();
    		
    		// Verifica se o nome da ação está correto
    		if(packageName.equals(action)) {
    			
    			// Verifica se houve permissão
    			if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
    				USBAccessoryManager.init(context);
    			}
    		}
    		
    		// Caso o acessório foi conectado no meio do processo
    		if(UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) {
    			USBAccessoryManager.init(context);
    		}
    		
    		// Caso o acessório foi conectado no meio do processo
    		else if (UsbManager.EXTRA_PERMISSION_GRANTED.equals(action)) {
    			USBAccessoryManager.init(context);
    		}

    		// Caso o acessório foi desconectado
    		else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
    			USBAccessoryManager.closeAccessory();
    		}
    	}	
    };
    
    private static void openAccessory() {
    	// Resgata FileDescriptor
		parcelFileDescriptor = deviceManager.openAccessory(accessory);
		
		// Caso o FileDescriptor for acessado
		if(parcelFileDescriptor != null) {
			// Declara que comunicação está OK
			enabled = true;
			open = true;
			
			// Abre streams
			outputStream = new FileOutputStream(parcelFileDescriptor.getFileDescriptor());
			byte[] teste = new byte[1];
			teste[0] = 10;
		}
		else {
			throw new USBAccessoryException("Could not open ParcelFileDescriptor.");
		}
    }
    
    public static void closeAccessory() {
    	
    	if(open == false) { return; }
    	
    	open = false;
    	enabled = false;
    	permissionRequested = false;
		
    	if(outputStream != null) {
			try {
				outputStream.close();
			} catch (IOException e) {
			}
    	}
    	
    	if(parcelFileDescriptor != null) {
    		try {
				parcelFileDescriptor.close();
			} catch (IOException ex) {
			}
    	}
		
    	outputStream = null;
    	parcelFileDescriptor = null;
    }
    
    public static void sendMessage(byte[] message) {
    	
    	if(outputStream != null) {
    		
    		try {
    			outputStream.write(message);
    			outputStream.flush();
    		}
    		catch(IOException ex) {
    		}
    		
    	}
    }
}
